#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <libutil.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include </sys/kern/syscalls.c>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/ktrace.h>

#include "kdump.h"
#include "sig.h"

void kd_sysret(struct ktr_header kd, int fd, t_args *args)
{
  struct ktr_sysret kd_ret;

  if (read(fd, &kd_ret, kd.ktr_len) < 0)
    exit(EXIT_FAILURE);
  printf("RET   %s", syscallnames[kd_ret.ktr_code]);
  if (kd_ret.ktr_error != 0)
    {
      printf(" -1 errno %d", kd_ret.ktr_error);
      if (!args->n)
	printf(" %s", strerror(kd_ret.ktr_error));
      printf("\n");
    }
  else
    printf(" %d\n", kd_ret.ktr_retval);
}

void kd_syscall(struct ktr_header kd, int fd, t_args* args)
{
  struct ktr_syscall kd_call;
  int ret, i;
  register_t reg;

  if (kd.ktr_len < (int)sizeof(kd_call))
    {
      if ((ret = read(fd, &kd_call, kd.ktr_len)) < 0)
	exit(EXIT_FAILURE);
    }
  else
    if ((ret = read(fd, &kd_call, sizeof(kd_call))) < 0)
      exit(EXIT_FAILURE);    
  printf("CALL  %s", syscallnames[kd_call.ktr_code]);
  if (kd_call.ktr_narg != 0)
    {
      if (*kd_call.ktr_args == 0)
	printf("(0");
      else if (args->d == 0)
	{
	  if (strstr(syscallnames[kd_call.ktr_code], "sig") && *kd_call.ktr_args >= FIRST_SIG  && *kd_call.ktr_args <= LAST_SIG)
	    printf("(%s", my_sig[*kd_call.ktr_args]);
	  else
	    printf("(0x%x", *kd_call.ktr_args);
	  
	}
      else
	printf("(%d", *kd_call.ktr_args);
      if (kd_call.ktr_narg == 1)
	printf(")");
      else
	printf(",");
      i = 0;
      while (i < kd_call.ktr_narg - 1)
	{
	  if (read(fd, &reg, sizeof(reg)) < 0)
	    exit(EXIT_FAILURE);
	  if (reg == 0)
	    printf("0");
	  else if (!args->d)
	    printf("0x%x", reg);
	  else
	    printf("%d", reg);
	  if (i + 1 != kd_call.ktr_narg - 1)
	    printf(",");
	  else
	    printf(")");
	  i++;
	}
    }
  printf("\n");
}

void kd_namei(struct ktr_header kd, int fd, t_args __attribute__((__unused__)) *args)
{
  char *buff;
  int ret;

  buff = malloc(kd.ktr_len);
  if ((ret = read(fd, buff, kd.ktr_len)) < 0)
    exit(EXIT_FAILURE);
  buff[ret] = '\0';
  printf("NAMI  \"%s\"\n", buff);
  free(buff);
}

void kd_genio(struct ktr_header kd, int fd, t_args* args)
{
  struct ktr_genio kd_gio;
  char*	buff;
  int ret, rest, bin;

  rest = kd.ktr_len - sizeof(struct ktr_genio);
  if (read(fd, &kd_gio, sizeof(struct ktr_genio)) < 0)
    exit(EXIT_FAILURE);
  buff = malloc(rest + 1);
  if ((ret = read(fd, buff, rest)) < 0)
    exit(EXIT_FAILURE);
  buff[ret] = '\0';
  printf("GIO   fd %d ", kd_gio.ktr_fd);
  if (kd_gio.ktr_rw == UIO_READ)
    printf("read");
  else if (kd_gio.ktr_rw == UIO_WRITE)
    printf("write");
  printf(" %d bytes\n", rest);
  if (!args->s)
    {
      for (ret = 0, bin = 0; ret < rest && bin == 0; ret++)
	{
	  if (buff[ret] >= 32 && buff[ret] < 127)
	    continue;
	  else if (buff[ret] == 10 || buff[ret] == 13 || buff[ret] == 0 || buff[ret] == 9)
	    continue;
	  bin = 1;
	}
      if (bin)
	{
	  if (args->m != -1 && args->m < (int) strlen(buff))
	    rest = args->m;
   	  my_hexdump(buff, rest);
	}
      else
	{
	  if (args->m != -1 && args->m < (int) strlen(buff))
	    buff[args->m] = '\0';
	  printf("\"%s\"\n", buff);
	}
    }
}

void kd_psig(struct ktr_header  __attribute__((__unused__)) kd, int  __attribute__((__unused__)) fd, t_args __attribute__((__unused__)) *args)
{
  printf("SIG");
}

void kd_csw(struct ktr_header  __attribute__((__unused__)) kd, int  __attribute__((__unused__)) fd, t_args  __attribute__((__unused__)) *args)
{
  printf("CSW");
}

void kd_user(struct ktr_header __attribute__((__unused__)) kd, int __attribute__((__unused__)) fd, t_args __attribute__((__unused__)) *args)
{
  printf("USER");
}

void kd_sysctl(struct ktr_header kd, int fd, t_args  __attribute__((__unused__)) *args)
{
  char *buffer;
  int ret;

  buffer = malloc(kd.ktr_len + 1);
  if ((ret = read(fd, buffer, kd.ktr_len)) < 0)
    exit(EXIT_FAILURE);
  buffer[ret] = '\0';
  printf("SCTL  \"%s\"\n", buffer);
  free(buffer);
}

void kd_struct(struct ktr_header kd, int fd, t_args* args)
{
  struct stat s;
  struct sockaddr sock;

  if (read(fd, &sock, kd.ktr_len - sizeof(struct stat)) < 0)
    exit(EXIT_FAILURE);
  if (read(fd, &s, sizeof(struct stat)) < 0)
    exit(EXIT_FAILURE);
  printf("STRU  ");
  print_stat(s, args);
  printf("\n");
}

